package main

import (
	"fmt"
	"os"
	_ "strconv"
	"sync"
	"time"
)

//var (
//	m  sync.Mutex
//	v1 int
//)

//func change(i int) {
//	m.Lock()
//	time.Sleep(time.Second)
//	v1 = v1 + 1
//	if v1%10 == 0 {
//		v1 = v1 - 10*i
//	}
//	m.Unlock()
//}

//func read() int {
//	m.Lock()
//	a := v1
//	m.Unlock()
//	return a
//}
//func main() {
//	var numGR = 21
//	var wg sync.WaitGroup
//	fmt.Printf("%d", read())
//	for i := 0; i < numGR; i++ {
//		wg.Add(1)
//		go func(i int) {
//			defer wg.Done()
//			change(i)
//			fmt.Printf(" - > %d ", read())
//		}(i)
//	}
//	wg.Wait()
//}

var Password = secret{password: "myPassword"}

type secret struct {
	RWM      sync.RWMutex
	M        sync.Mutex
	password string
}

//通过RWmutex写
func Change(c *secret, pass string) {
	c.RWM.Lock()
	fmt.Println("Chang with rwmutex lock")
	time.Sleep(3 * time.Second)
	c.password = pass
	c.RWM.Unlock()

}

//通过RWmutex读
func rwMutexShow(c *secret) string {
	c.RWM.RLock()
	fmt.Println("show with rwmutex ", time.Now().Second())
	time.Sleep(1 * time.Second)
	defer c.RWM.RUnlock()
	return c.password
}

//通过mutex读，和rwMutexShow的唯一区别在于锁的方式不同
func mutexShow(c *secret) string {
	c.M.Lock()
	fmt.Println("show with mutex.", time.Now().Second())
	time.Sleep(1 * time.Second)
	defer c.M.Unlock()
	return c.password
}

func main() {
	var show = func(c *secret) string { return "" }
	if len(os.Args) != 2 {
		fmt.Println("Using sync.RWMutex!", time.Now().Second())
		show = rwMutexShow
	} else {
		fmt.Println("Using sync.Mutex!", time.Now().Second())
		show = mutexShow
	}

	var wg sync.WaitGroup
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done()
			fmt.Println("Go pass:", show(&Password), time.Now().Second())
		}()
	}
	go func() {
		wg.Add(1)
		defer wg.Done()
		Change(&Password, "123456")
	}()
	wg.Wait()
}
